#include <iostream>
#include <signal.h>
#include <list>
#include <sys/socket.h>
#include "../socks/sock.h"
#include "../socks/sockdist.h"
#include <unistd.h>                  /*  for sleep()  */
#include <ncurses/ncurses.h>

using namespace std;


int descBRclient;
WINDOW * mainwin;

struct sigaction sig_quit;
void quit(int signal);
//(void)sa_handler (int)

void affichage(WINDOW * mainwin, string send, list<string> &text, list<string> &clients);
string recv_str(int desc);

int main(int argc, char** argv)
{
	sig_quit.sa_handler = quit;
	sigaction(SIGINT, &sig_quit, NULL);
	
	if(argc > 2)
	{
		if ( (mainwin = initscr()) == NULL ) {
			fprintf(stderr, "Error initialising ncurses.\n");
			exit(EXIT_FAILURE);
		}
		
		fd_set set;
		
		mvaddstr(1, 0, "Bienvenue dans le chat");
		mvaddstr(2, 0, "Entrer un nom ? ");
		refresh();
	
		string name;

		char c;
		bool b=true;
		do {
		//timeout(5);
			c = getch();
		
			if(c != -1)
			{
				if(c == 127)
				{
					if(name.length() >= 1)
					{ name.erase(name.length() - 1); }
				}
				else if(c == '\n')
				{
					b = false;
				}
				else
				{
					name+=c;
				}
			}
		} while(c && b);
	
		
		Sock BRclient(SOCK_STREAM, 0);
		
		if(BRclient.good())
		{
			descBRclient = BRclient.getsDesc();
		}
		
		SockDist BRserver(argv[1], (short) atoi(argv[2]));
		struct sockaddr_in * addrBRserver = BRserver.getAdrDist();
		int lgAddrBRserver = sizeof(struct sockaddr_in);
		
		int maxDesc = descBRclient + 1;
		struct timeval timeout;
		timeout.tv_usec = (long) (10000);
		
		mvaddstr(3, 0, "c ");
		refresh();
		
		int res = connect(descBRclient, (struct sockaddr*)addrBRserver, lgAddrBRserver);
		
		mvaddstr(4, 0, "1 ");
		refresh();
		
		int si = name.length();
		int sme = send(descBRclient, &si, sizeof(si), 0);
		int sName = send(descBRclient, name.c_str(), name.length(), 0);
		if(sName == -1)
		{
			cout << "bug !" << endl;
		}
		
		
		mvaddstr(5, 0, "2");
		refresh();
		
		int nbClient = 0;
		int res_nbc = recv(descBRclient, &nbClient, sizeof(nbClient), 0);
		
		mvaddstr(6, 0, "h");
		refresh();
		
		list<string> clients;
		for(int k(0); k<nbClient; k++)
		{
			string n = recv_str(descBRclient);
			n = n.substr(20);
			clients.push_back(n);
		}
		
		mvaddstr(6, 0, "3");
		refresh();
		
		list<string> chat;
		string c_send;
		
		wclear(mainwin);
		affichage(mainwin, c_send, chat, clients);
		
		while(true)
		{
			FD_ZERO(&set);
			FD_SET(descBRclient, &set);
			FD_SET(0, &set);
			
			int nbReady = select(maxDesc, &set, NULL, NULL, &timeout);
			
			if(nbReady > 0)
			{
				if( FD_ISSET(descBRclient, &set) )
				{
					///Traitement SERVER
					
					string c_recv = recv_str(descBRclient);
					
					if(c_recv[0] == '*' && c_recv[1] == '*')
					{
						string n = c_recv.substr(20);
						chat.push_front(c_recv);
						clients.push_back(n);
					}
					else if(c_recv[0] == '-' && c_recv[1] == '-')
					{
						chat.push_front(c_recv);
						string n = c_recv.substr(18);
						//chat.push_front(c_recv);
						//clients.push_back(n);
						for(list<string>::iterator l = clients.begin(); l != clients.end(); ++l)
						{
							if((*l) == n)
							{
								clients.erase(l);
								--l;
							}
						}
					}
					else
					{
						chat.push_front(c_recv);
					}
					
					affichage(mainwin, c_send, chat, clients);
				}
				
				if( FD_ISSET(0, &set) )
				{
					/// Traitement CIN
					c = getch();
		
					if(c == '\n')
					{
						int size = c_send.length();
						int res_send = send(descBRclient, &size, sizeof(c_send.length()), 0);
						res_send = send(descBRclient, c_send.c_str(), c_send.length(), 0);
					
						c_send.clear();
					}
					else if(c == 127)
					{
						if(c_send.length() >= 1)
						{ c_send.erase(c_send.length() - 1); }
					}
					else if(c != -1)
					{
						c_send += c;
					}
					
					affichage(mainwin, c_send, chat, clients);
					
				}
			}
			else
			{
				/// Timeout || Error
			}
			
			
			//timeout(0.1);
		}
		
		/*  Clean up after ourselves  */

		delwin(mainwin);
		endwin();
		refresh();
		
	}
	else
	{
		cout << "Aucun argument" << endl;
	}
}

void affichage(WINDOW * mainwin, string send, list<string> &text, list<string> &clients)
{
	wclear(mainwin);
	
	int k = 2;
	list<string>::iterator it = text.begin();
	
	while(it != text.end() && k < LINES - 4)
	{
		mvaddstr(LINES - k - 1, 0, (*it).c_str());
		++it;
		k++;
	}
	
	k = 2;
	for(list<string>::iterator ic = clients.begin(); ic != clients.end(); ++ic)
	{
		mvaddstr(k, COLS - (*ic).length() - 3, (*ic).c_str());
		k++;
	}
	
	
	string ecrit = "Ecrire : "+send;
	mvaddstr(LINES - 1, 2, ecrit.c_str());
	refresh();
}



string recv_str(int desc)
{
	int size = 0;
	int res_recv;
	
	res_recv = recv(desc, &size, sizeof(size), 0);
	if(res_recv == -1)
	{
		return "";
	}
	
	char *msg = new char[size+1];
	
	for(int k(0); k<size; k++)
	{
		res_recv = recv(desc, &msg[k], sizeof(msg[k]), 0);
		if(res_recv == -1)
		{
			cout << "!" << endl;
			msg[k] = '?';
		}
	}
	
	msg[size] = '\0';
	
	return (string)msg;
}


void quit(int signal)
{
	string c_send = "\\quit";
	int size = c_send.length();
	
	int res_send = send(descBRclient, &size, sizeof(c_send.length()), 0);
	res_send = send(descBRclient, c_send.c_str(), c_send.length(), 0);
	
	delwin(mainwin);
	endwin();
	refresh();
	
	exit(0);
}
